home *** CD-ROM | disk | FTP | other *** search
/ Aminet 33 / Aminet 33 - October 1999.iso / Aminet / dev / cross / ava-0.2.5.lha / ava-0.2.5 / src / Segment.C < prev    next >
Encoding:
C/C++ Source or Header  |  1999-03-23  |  19.9 KB  |  620 lines

  1. /*
  2.   Segment.C
  3.   Uros Platise, Dec 1998
  4.   
  5.   Even more powerful segments are provided that in earilier uAsm.
  6.   Any segment can now also be ref. as abstract segment or removable.
  7.   
  8.   * Abstract segments are those which are not put into executable file.
  9.   
  10.   * Removable segments allow additional feature on optimizing the size
  11.     of the executable file. If there is no call to removable segment,
  12.     it is simply removed.
  13. */
  14.  
  15. #include <stdio.h>
  16. #include <stdlib.h>
  17. #include <string.h>
  18. #include "Global.h"
  19. #include "Lexer.h"
  20. #include "Symbol.h"
  21. #include "Object.h"
  22. #include "Segment.h"
  23. #include "Reports.h"
  24.  
  25. TSegment::TSegment():segUsageCnt(1),fitted(false),errorActive(false){close();}
  26. void TSegment::close(){cseg=&segRec[SEG_ROOT];}
  27.  
  28. /* return true on creation */
  29. bool TSegment::set(const char* name){
  30.   TsegRecCI refidx;
  31.   TSegmentRec* cseg_bck=cseg;
  32.   /* find segment within refs ... */
  33.   for (refidx=cseg->segRef.begin();refidx!=cseg->segRef.end(); refidx++){
  34.     if (strcmp(name,(*refidx)->name)==0){
  35.       cseg=*refidx;
  36. #ifdef DEBUG      
  37.       reports.Info(TReports::VL_SEG4,"set=%s\n",cseg->name);
  38. #endif      
  39.       return false;
  40.     }
  41.   }
  42.   if (refidx==cseg->segRef.end()){
  43.     /* create child */
  44.     cseg->segRef.push_back(&segRec[segUsageCnt]);
  45.     cseg = &segRec[segUsageCnt++];
  46.     cseg->parent = cseg_bck;
  47.     
  48.     /* If parent is removable, child is also removable and so abstract */
  49.     cseg->flags |= cseg_bck->flags;
  50.     strcpy(cseg->name,name);    /* assign name */
  51.     strcat(cseg->label,cseg_bck->label);
  52.     strcat(cseg->label,"_");strcat(cseg->label,name);
  53.     
  54.     /* if parent alignment size differs and our is not 1 report error.
  55.        Otherwise if our is 1, take parents one */
  56.     if (cseg->align==1){cseg->align=cseg_bck->align;}
  57.     else if (cseg->align < cseg_bck->align){
  58.       throw syntax_error("Align size missmatch with parent for: ",
  59.         cseg->name);
  60.     }    
  61.     /* create external symbol (to satisfy macro check) */
  62.     symbol.addInternalLabel(cseg->label);
  63.   }
  64.   return true;
  65. }
  66.  
  67. void TSegment::setPrevious(){assert(cseg->parent!=NULL); cseg=cseg->parent;}
  68.  
  69. /* Update current segment attributes, size and abs */
  70. void TSegment::update(const TSegmentRec& tmpSeg){
  71.   /* if current size is bigger than new one, error! */
  72.   /*
  73.   if (cseg->size!=-1 && tmpSeg.size!=-1 && cseg->size > tmpSeg.size){  
  74.     reports.Warnning("Segment `%s': previous size: $%lx  new size: $%lx",
  75.       cseg->name, cseg->size, tmpSeg.size);
  76.     throw syntax_error("Segment size already declared for: ",cseg->name);
  77.   }
  78.   */
  79.  
  80.   if (cseg->size < tmpSeg.size){cseg->size=tmpSeg.size;}
  81.   
  82.   cseg->PC += tmpSeg.PC;      /* add current PC */
  83.   
  84.   /* absolute address */
  85.   if (cseg->abs!=-1 && tmpSeg.abs!=-1 && cseg->abs!=tmpSeg.abs){
  86.     throw syntax_error("Absolute address already declared for: ",cseg->name);}
  87.   if (tmpSeg.abs!=-1){cseg->abs=tmpSeg.abs;}
  88.  
  89.   /* if stored segment is not yet abstract and segTmp is, make cseg too */
  90.   cseg->flags |= tmpSeg.flags & TSegmentRec::Abstract;
  91.   
  92.   /* if stored segment is removable but this one is not, clear removable flag*/
  93.   cseg->flags &= (0xff-TSegmentRec::Removable) |
  94.     (tmpSeg.flags & TSegmentRec::Removable);  
  95.   
  96.   /* check align size - error only if new differs from 1 */
  97.   if (cseg->align!=tmpSeg.align && tmpSeg.align>1){
  98.     printf("cseg=%d, tmp=%d\n", cseg->align, tmpSeg.align);
  99.     throw syntax_error("Align size missmatch for segment: ", cseg->name);
  100.   }    
  101.   /* mirror redeclaration check if and only if tmpSeg is not existing segment */
  102.   if (cseg != &tmpSeg && cseg->mirrorType && tmpSeg.mirrorType){
  103.     throw syntax_error("Mirror segment was already declared for: ",
  104.       cseg->name);
  105.   }
  106. }
  107.  
  108. /*
  109.   OBSOLETE FUNCTION --- TO BE REMOVED
  110. */
  111. #ifdef CHECK_OBSOLTE
  112. void TSegment::checkOBSOLETE(const TSegmentRec& segTemplate){
  113.   /* if stored segment is not yet abstract and segTmp is, make cseg too */
  114.   cseg->flags |= segTemplate.flags & TSegmentRec::Abstract;
  115.   
  116.   /* if stored segment is removable but this one is not, clear removable flag*/
  117.   cseg->flags &= (0xff-TSegmentRec::Removable) |
  118.     (segTemplate.flags & TSegmentRec::Removable);
  119.          
  120.   /* Compare other attributes as size and abs */
  121.   if (segTemplate.abs!=-1){
  122.     if (cseg->abs==-1){cseg->abs=segTemplate.abs;}
  123.     else if (cseg->abs!=segTemplate.abs){
  124.       throw segment_error("Segment absolute address missmatch.");}
  125.   }
  126.   if (segTemplate.size!=-1){
  127.     if (cseg->size==-1){cseg->size=segTemplate.size;}
  128.     else if (cseg->size!=segTemplate.size){
  129.       throw segment_error("Segment size missmatch.");}
  130.   }
  131. }
  132. #endif
  133.  
  134. /*
  135.   New segment is build upon segRec[segUsageCnt] what was suggested
  136.   by the set function.
  137. */
  138. bool TSegment::parse(){  
  139.   TSegmentRec& segTemplate = segRec[segUsageCnt];  
  140.   segTemplate.clear();
  141.     
  142.   if (segUsageCnt==MAX_SEGMENTS){
  143.     throw generic_error("Maximum number of segments is reached.\n"
  144.                         "Increase MAX_SEGMENTS variable in Segment.h file.");
  145.   }  
  146.   if (strcmp(lxP->string,"seg")!=0){return false;}
  147.   /* parse flags */
  148.   WHILE_TOKEN{
  149.     if (lxP->type!=TlxData::STRING){
  150.       throw syntax_error("Bad format",lxP->string);}
  151.             
  152.     if (strcmp(lxP->string,"removable")==0){
  153.       segTemplate.flags|=TSegmentRec::Removable;}
  154.     else if (strcmp(lxP->string,"abstract")==0){
  155.       segTemplate.flags|=TSegmentRec::Abstract;}
  156.     else if (strcmp(lxP->string,"abs")==0){segTemplate.abs=parseValue();}
  157.     else if (strcmp(lxP->string,"size")==0){segTemplate.size=parseValue();}
  158.     else if (strcmp(lxP->string,"align")==0){segTemplate.align=parseValue();}
  159.     else if (strcmp(lxP->string,"mirror")==0){
  160.       GET_TOKEN;
  161.       if (strcmp(lxP->string,"=")){
  162.         throw syntax_error("Bad format at ",lxP->string);}
  163.       parseSegment(true);      
  164.       segTemplate.mirrorType = TSegmentRec::NoCompression;
  165.       segTemplate.mirrorSegNo = getSegNo();
  166.     }
  167.     else{break;}
  168.   }
  169.   PUT_TOKENBACK;
  170.   
  171.   /* parse segment name with its segTemplate */
  172.   parseSegment();
  173.   update(segTemplate);
  174.   
  175.   char buf [SEG_LABELLEN];  
  176.   object.outSegment(cseg-segRec);
  177.   object.outPCMarker(getPC(buf));  
  178.   return true;
  179. }
  180.  
  181. long TSegment::parseValue(){
  182.   /* expecting = */
  183.   GET_TOKEN;
  184.   if (strcmp(lxP->string,"=")){
  185.     throw syntax_error("Bad format at ",lxP->string);}
  186.   GET_TOKEN;
  187.   if (lxP->type!=TlxData::LVAL){
  188.     throw syntax_error("Value expected at ",lxP->string);}
  189.   return lxP->lval;
  190. }
  191.  
  192. void TSegment::parseSegment(bool mirror=false){  
  193.   close();            /* go to root first */
  194.   do{
  195.     lexer._gettoken();
  196.     if (lxP->type!=TlxData::STRING){
  197.       throw syntax_error("Segment line without segment name.");}
  198.     bool newSeg = set(lxP->string);
  199.     if (mirror && newSeg){
  200.       throw segment_error("Mirror segment is not declared yet: ",lxP->string);}
  201.     GET_TOKEN;    /* get delimiter - full stop, which seperates segments ... */
  202.   }while(lxP->type==TlxData::CONTROL && lxP->string[0]=='.');  
  203.   PUT_TOKENBACK;
  204. }
  205.  
  206. /* 
  207.   It returns current program counter relative to segment
  208. */
  209. char* TSegment::getPC(char* PC_str){
  210.   if (cseg==NULL || cseg==segRec)
  211.     {throw segment_error("Code is present out of segment.");}
  212.   sprintf(PC_str,"(%s+$%lx)",cseg->label,cseg->PC);
  213.   /* increase segment reference count */
  214.   return PC_str;
  215. }
  216.  
  217. void TSegment::incPC(long relative){
  218.   if (cseg==NULL || cseg==segRec){
  219.     throw segment_error("Code is present out of segment.");}
  220.   cseg->PC+=relative;
  221.   if (cseg->size!=-1 && cseg->PC > cseg->size){
  222.     throw segment_error("Segment full: ",cseg->name);}  
  223. }
  224.  
  225. void TSegment::removeUnused(){
  226.   for (int si=1;si<segUsageCnt;si++){
  227.     if (segRec[si].refCount==0 && segRec[si].flags==TSegmentRec::Removable){
  228.       segRec[si].status|=TSegmentRec::Removed;
  229.       symbol.undefine(segRec[si].label);}}
  230. }
  231.  
  232. bool TSegment::isEnabled(int segNo){
  233.   return !(segRec[segNo].status & TSegmentRec::Removed);
  234. }
  235.  
  236. bool TSegment::isAbstract(int segNo){
  237.   return (segRec[segNo].flags & TSegmentRec::Abstract);
  238. }
  239.  
  240.  
  241. /* FITTER and its FACILITIES */
  242.  
  243. /* segment own size plus size of all childs
  244.    check for badly removed segments! 
  245.    level=0 (ROOT_SEG), level=1 (BASE_SEGMENTS), level=2 (CHILDS of BASE_SEG)
  246. */
  247. void TSegment::findSum(TSegmentRec* segp, int level=0){
  248. #ifdef DEBUG
  249.   reports.Info(TReports::VL_SEG4,"findSum()\n");
  250. #endif  
  251.  
  252.   if (segp->status & TSegmentRec::Removed){segp->sumSize=0;return;}
  253.   
  254.   /* For all childs flash.ch1, flash.ch2, ... do the following:
  255.      if segment is fixed size, add ->size parameter otherwise PC */
  256.   if (segp->size!=SEG_UNKNOWNSIZE && level>=2){
  257.     segp->sumSize+=segp->size;}else{segp->sumSize += segp->PC;}  
  258.   
  259.   TsegRecCI segRecCI;
  260.   for (segRecCI=segp->segRef.begin();segRecCI!=segp->segRef.end();segRecCI++){
  261.     findSum(*segRecCI, level+1); segp->sumSize += (*segRecCI)->sumSize;}
  262.  
  263.   /* align size */
  264.   int alignBytes = segp->sumSize % segp->align;
  265.   if (alignBytes>0){
  266.     alignBytes = segp->align - alignBytes;
  267.     reports.Info(TReports::VL_SEG1,
  268.       "Extending segment `%s' for %d extra byte(s) to align it.\n",
  269.       segp->name, alignBytes);
  270.     segp->sumSize += alignBytes;
  271.     if (segp->size != SEG_UNKNOWNSIZE){
  272.       throw segment_error("Cannot resize fixed size segment: ",
  273.         segp->name);
  274.     }
  275.   }           
  276.   
  277.   /* if segment's maximum size is not defined, let's define it */
  278.   if (segp->size==SEG_UNKNOWNSIZE){segp->size=segp->sumSize;}   
  279.         
  280.   /* check range */
  281.   if (segp->sumSize > segp->size){
  282.     segp->status |= TSegmentRec::OutofRange;errorActive=true;
  283.     reports.Info(TReports::VL_ALL,"Not enough space for `%s': "
  284.       "req=%ld avail=%ld bytes\n",
  285.       segp->name, segp->sumSize, segp->size);
  286.   }
  287. #ifdef DEBUG
  288.   reports.Info(TReports::VL_SEG4," %s: sum = %ld, size= %ld\n", 
  289.     segp->name, segp->sumSize, segp->size);
  290. #endif    
  291. }
  292.  
  293. /*
  294.   Before calling findsum function, mirror segment must
  295.   be declared.
  296. */
  297. void TSegment::CalcMirrors(){
  298.   /* set mirrors */
  299.   for (int i=0; i < segUsageCnt; i++){
  300.     if (segRec[i].mirrorType & TSegmentRec::NoCompression){
  301.       /* get new segment number and set PC */
  302.       segRec[i].mirrorSegNo = 
  303.         preproc.csrc->segP->seg[segRec[i].mirrorSegNo].newNo;
  304.       segRec[segRec[i].mirrorSegNo].PC = segRec[i].PC;
  305.     }
  306.     if (segRec[i].mirrorType & TSegmentRec::RLE1){
  307.       throw generic_error("RLE1 is not supported yet.\n");}
  308.   }
  309. }
  310.  
  311. /* Segment Child Sort Function
  312.  
  313.    - Abstract segments are pushed after non-Abstract segs.
  314.    - and higher absolute value to the bottom
  315. */
  316. #define RFS_FUNC(abs, ntype, type)    ((!(ntype) & (abs)) | (type))
  317.  
  318. void TSegmentRec::sortRefs(){
  319.   vector< TSegmentRec* >::iterator ri;
  320.   bool update=true;
  321.   bool ntype;
  322.   while(update==true){
  323.     update=false; 
  324.     for (ri=segRef.begin(); (ri+1) < segRef.end(); ri++){
  325.     
  326.       ntype = ((*ri)->flags&TSegmentRec::Abstract) <
  327.                 ((*(ri+1))->flags&TSegmentRec::Abstract);
  328. /*            
  329.       printf("%s,%lx,%d / %s,%lx,%d  (ntype=%d)\n", 
  330.         (*ri)->name, (*ri)->abs, (*ri)->flags, 
  331.     (*(ri+1))->name, (*(ri+1))->abs, (*(ri+1))->flags, ntype);
  332. */    
  333.       if (RFS_FUNC( (*ri)->abs > ((*(ri+1))->abs),
  334.                   ntype,
  335.                   ((*ri)->flags&TSegmentRec::Abstract) >
  336.                 ((*(ri+1))->flags&TSegmentRec::Abstract) )){
  337.         update=true; TSegmentRec* buf=*ri; *ri=*(ri+1); *(ri+1)=buf;
  338. //    printf("swap\n");
  339.       }
  340.     }
  341.   }
  342. }
  343.  
  344. void TSegment::fit(TSegmentRec* segp){
  345.   /* if removed, skip it! */
  346.   if (segp->status & TSegmentRec::Removed){return;}
  347. #ifdef DEBUG
  348.   reports.Info(TReports::VL_SEG4,"\nfitting `%s'\n", segp->name);
  349. #endif  
  350.   TMicroStack<TSSRec> notPlaced(segp->segRef.size());
  351.   TMicroStack<TSSRec> freeArea(segp->segRef.size()+1);
  352.   TsegRecI sgci;
  353.   
  354.   /* sort already fixed segments by its absolute address */  
  355.   segp->sortRefs();
  356.  
  357.   /* get starting address */
  358.   long stAddr, stEnd;
  359.   if (segp->abs==SEG_NOTPLACED){
  360.     throw syntax_error("Absolute address of the base segment not defined: ",
  361.       segp->name);}
  362.   stAddr = segp->start();
  363.   
  364.   /* get free area and fixed (already placed) segments
  365.      Since refs are sorted by abs, not placed segments will come first */
  366.   for(sgci=segp->segRef.begin(); sgci != segp->segRef.end(); sgci++){  
  367.     if ((*sgci)->abs==SEG_NOTPLACED){
  368.     
  369.       if (!((*sgci)->status & TSegmentRec::Removed)){      
  370.         /* remove zero bytes segments and set their offset to the end
  371.        of the parent code */
  372.     if ((*sgci)->sumSize==0){
  373.       (*sgci)->abs = stAddr;
  374.     } else {
  375.           notPlaced.push(TSSRec((*sgci)->sumSize,*sgci));     
  376.     }
  377.       }
  378.     }    
  379.     else{
  380.       stEnd = (*sgci)->abs;
  381.       if ((stEnd-stAddr) > 0){freeArea.push(TSSRec(stAddr,stEnd));}
  382.       else if ((stEnd-stAddr)<0){
  383.         (*sgci)->status |= TSegmentRec::Collision;errorActive=true;}
  384.       stAddr = (*sgci)->end();
  385.       if ((segp->size-stAddr)<0){
  386.         (*sgci)->status |= TSegmentRec::OutofRange;errorActive=true;}
  387.     }
  388.   }  
  389.   /* add free tail */  
  390.   stEnd = segp->abs + segp->size;
  391.   if ((stEnd-stAddr) > 0){freeArea.push(TSSRec(stAddr,stEnd));}
  392.  
  393. #ifdef DEBUG    
  394.   /* print free space */
  395.   for(int i=0;i<freeArea.size();i++){
  396.     reports.Info(TReports::VL_SEG4,"free: [$%lx,$%lx]\n",
  397.       freeArea[i].start,freeArea[i].end());
  398.   }      
  399. #endif     
  400.   
  401.   /* fit floating segments - bigger to bigger holes in the front */
  402.   notPlaced.sort();
  403.   TSSRec *freeSeg, *npSeg;    /* ref to: free and notplaced segment */
  404.   while(notPlaced.size()>0){  
  405.     freeArea.sort();
  406.     if (freeArea.size()==0){
  407.       errorActive=true;
  408.       while(notPlaced.size()>0){
  409.         notPlaced.top().ref->status|=TSegmentRec::OutofRange;notPlaced.pop();}
  410.       break;
  411.     }
  412.     freeSeg = &freeArea.top(); npSeg = ¬Placed.top();
  413.         
  414.     /* take top one and put into top free space -
  415.        if operation fails, mark all remaining segments OutofRange */
  416. #ifdef DEBUG       
  417.     reports.Info(TReports::VL_SEG4,"alloc: [$%lx,$%lx] $%lx, $%lx\n", 
  418.       freeSeg->start,freeSeg->end(),freeSeg->size, npSeg->size);
  419. #endif      
  420.     if (freeSeg->size < npSeg->size){
  421.       errorActive=true;
  422.       while(notPlaced.size()>0){
  423.         notPlaced.top().ref->status|=TSegmentRec::OutofRange;notPlaced.pop();}
  424.     }else{
  425. #ifdef DEBUG    
  426.       reports.Info(TReports::VL_SEG4,"setting seg: `%s' with size = $%lx\n", 
  427.                    npSeg->ref->name, npSeg->ref->sumSize);
  428. #endif           
  429.       npSeg->ref->abs = freeSeg->start;
  430.       freeSeg->start += npSeg->ref->sumSize;
  431.       freeSeg->size  -= npSeg->ref->sumSize; /*decrease size of the free area*/
  432.       notPlaced.pop();
  433.     }
  434.   }  
  435.   /* Fit all childs too */
  436.   for(sgci=segp->segRef.begin();sgci!=segp->segRef.end();sgci++){fit(*sgci);}
  437. }
  438.  
  439. void TSegment::fitter(){
  440.   removeUnused();
  441.   CalcMirrors();
  442.   findSum(segRec);
  443.   if (!errorActive){
  444.     /* fit every sub-segment of the root segment separately */
  445.     TsegRecCI segRecCI=segRec[SEG_ROOT].segRef.begin();
  446.     for (;segRecCI!=segRec[SEG_ROOT].segRef.end(); segRecCI++){fit(*segRecCI);}
  447.     fitted=true;
  448.   }
  449.   Report();
  450.   if (errorActive==true){
  451.     throw generic_error("Cannot fit all segments."
  452.       " See segment tree for details.");
  453.   }
  454. }
  455.  
  456. /* Adjust Segment Labels to Current File */
  457. void TSegment::adjustSegments(){
  458.   char labelValue [LX_STRLEN];
  459.   for (int si=1; si<segUsageCnt; si++){
  460.     if (segRec[si].status & TSegmentRec::Removed){continue;}
  461.     sprintf(labelValue,"$%lx",segRec[si].abs+preproc.csrc->segP->seg[si].rel);
  462.     symbol.modifyValue(segRec[si].label, labelValue);
  463.   }
  464. }
  465.  
  466.  
  467. #define SAVE_NONE    0
  468. #define SAVE_ROOTINFO    1
  469. #define SAVE_GOBACK    2
  470.  
  471. void TSegment::saveSegments(){
  472.   if (cseg==NULL){
  473.     reports.Warnning(TReports::Segments,"File does not contain program code.");
  474.     return;
  475.   }
  476.   saveSegmentTree(&segRec[SEG_ROOT]);
  477.  
  478. void TSegment::saveSegmentTree(TSegmentRec* p){
  479.   if (p!=segRec){
  480.     
  481.     object.outOperand(p->PC);
  482.     object.outOperand(p->size);
  483.     object.outOperand(p->abs);
  484.     object.outOperand(p->flags);
  485.     object.outOperand(p->mirrorType);
  486.     object.outOperand(p->mirrorSegNo);
  487.     object.outOperand(p->align);
  488.     object.outOperand(p-segRec);         /* report segment number! */
  489.     object.outStringOperand(p->name);;
  490.     object.outSegmentData(SAVE_ROOTINFO);    /* root information */
  491.   }
  492.   TsegRecCI segRecCI;
  493.   for (segRecCI=p->segRef.begin(); segRecCI != p->segRef.end(); segRecCI++){
  494.     if (!((*segRecCI)->status & TSegmentRec::Removed)){
  495.       saveSegmentTree(*segRecCI);}}
  496.   if (p!=segRec){object.outSegmentData(SAVE_GOBACK);}    /* one back ... */
  497. }
  498.  
  499. void TSegment::loadSegments(int segNo){
  500.   TSegmentRec& segTemplate = segRec[segUsageCnt];
  501.   if (segNo==SAVE_GOBACK){setPrevious();return;}
  502.   if (segNo!=SAVE_ROOTINFO){
  503.     throw syntax_error("Invalid segment direction. Object file corrupted.");}  
  504.  
  505.   int objSegNo            =      object.popOperand();
  506.   segTemplate.align       = (int)object.popOperand();
  507.   segTemplate.mirrorSegNo = (int)object.popOperand();
  508.   segTemplate.mirrorType  = (int)object.popOperand();
  509.   segTemplate.flags       = (int)object.popOperand();
  510.   segTemplate.abs         =      object.popOperand();
  511.   segTemplate.size        =      object.popOperand();
  512.   segTemplate.PC          =      object.popOperand();
  513.   
  514.   if (set(object.popStringOperand())==false){
  515.     preproc.csrc->segP->seg[cseg-segRec].rel = cseg->PC;
  516.     update(segTemplate);
  517.   }
  518.   preproc.csrc->segP->seg[objSegNo].newNo = cseg-segRec;
  519. /* 
  520.   printf("`%s' PC=$%lx, nN=%d, cPx=%d, mirror=%d\n", cseg->name, 
  521.     preproc.csrc->segP->seg[objSegNo].rel,
  522.     preproc.csrc->segP->seg[objSegNo].newNo,
  523.     segTemplate.mirrorType, segTemplate.mirrorSegNo);
  524. */
  525. }
  526.  
  527. void TSegment::Report(){
  528.   /* Print Segment Tree */
  529.   reports.Info(TReports::VL_SEG1, "\n%-30.30s   %8.8s   %8.8s %8.8s\n", 
  530.     "SEGMENT TREE:", "ABS", "SIZE", "FLAGS");
  531.   ReportSegmentTree(segRec,0);
  532.   reports.Info(TReports::VL_SEG1, "\n");
  533.   
  534.   /* Overall Segment Information */
  535.   if (fitted==false){return;}
  536.   reports.Info(TReports::VL_SEG1, "%-30.30s   %10.10s %10.10s %10.10s\n", 
  537.     "OVERALL SEGMENT INFO:", "SUM SIZE", "MAX SIZE", "USAGE [%]");
  538.   
  539.   TsegRecCI segRecCI;
  540.   for (segRecCI=segRec[SEG_ROOT].segRef.begin(); 
  541.        segRecCI!=segRec[SEG_ROOT].segRef.end(); segRecCI++){
  542.          ReportOverall(*segRecCI);}
  543.   reports.Info(TReports::VL_SEG1, "\n");
  544. }
  545.  
  546. void TSegment::ReportSegmentTree(TSegmentRec* p, int level){
  547.   if (p!=&segRec[SEG_ROOT]){
  548.     reports.Info(TReports::VL_SEG1, 
  549.       "%*.0s%c %-*.*s", level, "", (level==2)?'+':'*',
  550.       SEG_MAXNAMELEN-level, SEG_MAXNAMELEN-level, p->name);      
  551.       
  552.     if (p->abs==-1 || fitted==false){
  553.       reports.Info(TReports::VL_SEG1, "     -     ");
  554.     }
  555.     else{reports.Info(TReports::VL_SEG1, " $%8.8lx ",p->abs);}
  556.     if (p->PC==0){reports.Info(TReports::VL_SEG1, "     .     ");}
  557.     else{reports.Info(TReports::VL_SEG1, " $%8.8lx ",p->PC);}
  558.  
  559.     if (p->flags&TSegmentRec::Abstract){
  560.       reports.Info(TReports::VL_SEG1, "Abstract ");
  561.     }
  562.     if (p->flags&TSegmentRec::Removable){
  563.       if (p->status & TSegmentRec::Removed){
  564.         reports.Info(TReports::VL_SEG1, "*REMOVED*");
  565.       }
  566.       else{reports.Info(TReports::VL_SEG1, "Removable ");}
  567.     }
  568.     reports.Info(TReports::VL_SEG1, "\n");
  569.     if (p->status!=TSegmentRec::Ok && p->status!=TSegmentRec::Removed){
  570.       reports.Info(TReports::VL_SEG1, "%*.0s  ^ STATUS: ", level, "");
  571.       if (p->status & TSegmentRec::OutofRange){
  572.         reports.Info(TReports::VL_SEG1, "Overflown ");
  573.       }
  574.       if (p->status & TSegmentRec::Collision){
  575.         reports.Info(TReports::VL_SEG1, "Collision ");
  576.       }
  577.       reports.Info(TReports::VL_SEG1, "\n");
  578.     }
  579.   }
  580.   TsegRecCI segRecCI;
  581.   p->sortRefs();
  582.   for (segRecCI=p->segRef.begin(); segRecCI != p->segRef.end(); segRecCI++){
  583.     ReportSegmentTree(*segRecCI, level+2);}
  584. }
  585.  
  586. void TSegment::ReportOverall(TSegmentRec* p){
  587.   float usage;
  588.   if (p->size==0){usage=0;}
  589.   else{usage=(100.0*(float)p->sumSize)/(float)(p->size);}
  590.   reports.Info(TReports::VL_SEG1, "  + %-30.30s $%8.8lx  $%8.8lx   %.1f\n", 
  591.     p->name, p->sumSize, p->size, usage);
  592. }
  593.  
  594. char* TSegment::TellBaseSegment(int segNo){
  595.   assert(segNo>0);
  596.   TSegmentRec* p = &segRec[segNo];  
  597.   while(p->parent != segRec){p=p->parent;} /*go up and find parent=segrec*/
  598.   return p->name;
  599. }
  600.  
  601. char* TSegment::TellSegmentName(int segNo){
  602.   assert(segNo>0);
  603.   return segRec[segNo].name;
  604. }
  605.  
  606. int TSegment::TellNoSegments(){
  607.   return segUsageCnt;
  608. }
  609.  
  610. int TSegment::TellMirror(int segNo){
  611.   if (segRec[segNo].mirrorType==TSegmentRec::NoMirror){return -1;}
  612.   return segRec[segNo].mirrorSegNo;
  613. }
  614.  
  615. int TSegment::TellAlign(int segNo){
  616.   return segRec[segNo].align;
  617. }
  618.  
  619.